package com.ziyueyuwen.xiniao.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.suyeer.basic.util.LogUtil;
import com.suyeer.fastwechat.bean.fwpay.FwPrepayBean;
import com.suyeer.fastwechat.bean.fwpay.FwQueryOrderResult;
import com.suyeer.fastwechat.util.FwPayUtil;
import com.ziyueyuwen.xiniao.base.HttpResContent;
import com.ziyueyuwen.xiniao.bean.ZyClassInfo;
import com.ziyueyuwen.xiniao.bean.ZyCourseInfo;
import com.ziyueyuwen.xiniao.bean.ZyOrderAddress;
import com.ziyueyuwen.xiniao.bean.ZyUser;
import com.ziyueyuwen.xiniao.bean.product.ProductVO;
import com.ziyueyuwen.xiniao.bean.product.ZyCouponDO;
import com.ziyueyuwen.xiniao.bean.product.ZyOrderDO;
import com.ziyueyuwen.xiniao.bean.wx.TbWxUserInfo;
import com.ziyueyuwen.xiniao.dao.*;
import com.ziyueyuwen.xiniao.enums.CouponStatusEnum;
import com.ziyueyuwen.xiniao.enums.OrderStatusEnum;
import com.ziyueyuwen.xiniao.service.ClassUserService;
import com.ziyueyuwen.xiniao.service.OrderService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.ziyueyuwen.xiniao.enums.OrderStatusEnum.SUCCESS;
import static com.ziyueyuwen.xiniao.util.ConstUtil.*;

/**
 * @author jun 2019/2/25
 */
@Service
public class OrderServiceImpl implements OrderService {

    private final String NOTIFY_URL = "https://wx.ziyueyuwen.com/api/product/order/notify.do";

    private final Integer ZY_ORDER_CODE = 1000000;

    @Autowired
    private ZyProductInfoMapper zyProductInfoMapper;

    @Autowired
    private ZyCouponMapper zyCouponMapper;

    @Autowired
    private ZyOrderMapper zyOrderMapper;

    @Autowired
    private ZyClassInfoMapper zyClassInfoMapper;

    @Autowired
    private ZyOrderAddressMapper zyOrderAddressMapper;

    @Autowired
    private ZyCourseInfoMapper zyCourseInfoMapper;

    @Autowired
    private ClassUserService classUserService;

    @Override
    public Boolean add(ZyOrderDO zyOrderDO) {
        return zyOrderMapper.add(zyOrderDO);
    }

    @Override
    public Boolean updateByWxNotify(ZyOrderDO zyOrderDO) {
        return zyOrderMapper.updateByWxNotify(zyOrderDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject getPrepayInfo(HttpResContent hrc, Integer productId, Integer addressId, Integer couponId) throws Exception {
        ZyUser zyUser = hrc.getUserInfo();
        TbWxUserInfo wxUserInfo = hrc.getWxUserInfo();
        ProductVO productVO = zyProductInfoMapper.selectProduct(productId);
        if (productVO == null) {
            throw new Exception("商品不存在!");
        }
        if (!productVO.getIfUpperShelf()) {
            throw new Exception("此班级已满员!");
        }
        ZyClassInfo zyClassInfo = zyClassInfoMapper.selectByPrimaryKey(productVO.getClassId());
        if (zyClassInfo == null) {
            throw new Exception("班级不存在!");
        }
        ZyOrderAddress zyOrderAddress = zyOrderAddressMapper.selectByPrimaryKey(addressId);
        if (zyOrderAddress == null) {
            throw new Exception("收货地址不存在!");
        }
        if (zyOrderMapper.checkHaveBuyProduct(zyUser.getUserAccount(), productVO.getClassId())) {
            throw new Exception("您已购买过此商品!");
        }
        ZyCourseInfo zyCourseInfo = zyCourseInfoMapper.selectByPrimaryKey(productVO.getCourseId());
        int couponPrice = getCouponPrice(couponId, zyUser.getUserAccount());
        int totalFee = productVO.getPrice() - couponPrice;
        if (totalFee < 1) {
            throw new Exception("该优惠券不可用!");
        }
        String outTradeNoPreFix = String.valueOf(ZY_ORDER_CODE + productId);
        FwPrepayBean fwPrepayBean = new FwPrepayBean(wxUserInfo.getOpenid(), productVO.getProductName(), totalFee,
                hrc.getUserIp(), NOTIFY_URL, outTradeNoPreFix);
        JSONObject retObj = FwPayUtil.getPayParams(fwPrepayBean);

        ZyOrderDO zyOrderDO = new ZyOrderDO();
        zyOrderDO.setProductId(productId);
        zyOrderDO.setProductName(productVO.getProductName());
        zyOrderDO.setUserAccount(zyUser.getUserAccount());
        zyOrderDO.setUserName(zyUser.getUserName());
        zyOrderDO.setCourseName(zyCourseInfo.getCourseName());
        zyOrderDO.setClassId(productVO.getClassId());
        zyOrderDO.setClassName(zyClassInfo.getClassName());
        zyOrderDO.setCouponId(couponId);
        zyOrderDO.setCouponPrice(couponPrice);
        zyOrderDO.setOriginalPrice(productVO.getPrice());
        zyOrderDO.setSellPrice(totalFee);
        zyOrderDO.setOutTradeNo(fwPrepayBean.getOut_trade_no());
        zyOrderDO.setCustomerUnionId(wxUserInfo.getUnionid());
        zyOrderDO.setCustomerNickName(wxUserInfo.getNickname());

        zyOrderDO.setOrderName(zyOrderAddress.getConsignee());
        zyOrderDO.setOrderPhoneNum(zyOrderAddress.getConsigneeAccount());
        zyOrderDO.setOrderZone(zyOrderAddress.getArea());
        zyOrderDO.setOrderAddress(zyOrderAddress.getAddress());
        if (!zyOrderMapper.add(zyOrderDO)) {
            throw new Exception("创建订单失败!");
        }
        retObj.put(KEY_OUT_TRADE_NO, zyOrderDO.getOutTradeNo());
        return retObj;
    }

    @Override
    public void enableUse(String outTradeNo, String unionId) throws Exception {
        ZyOrderDO zyOrderDO = zyOrderMapper.getByOutTradeNo(outTradeNo);
        if (zyOrderDO == null) {
            throw new Exception("订单不存在!");
        }
        if (!zyOrderDO.getCustomerUnionId().equals(unionId)) {
            throw new Exception("无效的订单账号!");
        }
        if (zyOrderDO.getOrderStatus() == SUCCESS) {
            throw new Exception("优惠券已使用成功!");
        }
        zyCouponMapper.enableUse(zyOrderDO.getCouponId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payBack(String notifyContent) throws Exception {
        FwQueryOrderResult fwQueryOrderResult = FwPayUtil.checkPayBackNotify(notifyContent);
        OrderStatusEnum statusEnum = WX_RESPONSE_STATUS_SUCCESS.equalsIgnoreCase(fwQueryOrderResult.getTrade_state()) ? SUCCESS : OrderStatusEnum.FAILURE;
        ZyOrderDO zyOrderDO = zyOrderMapper.getByOutTradeNo(fwQueryOrderResult.getOut_trade_no());
        if (zyOrderDO != null) {
            zyOrderDO.setTransactionId(fwQueryOrderResult.getTransaction_id());
            zyOrderDO.setOrderStatus(statusEnum);
            if (!zyOrderMapper.updateByWxNotify(zyOrderDO)) {
                throw new Exception("更新支付订单失败!");
            }
        }
        LogUtil.info(JSON.toJSONString(fwQueryOrderResult));
        if (statusEnum == SUCCESS) {
            try {
                classUserService.addClassStudentFromProduct(zyOrderDO.getClassId(), zyOrderDO.getUserAccount());
            } catch (Exception e) {
                LogUtil.error("微信支付回调后添加学生到班级失败, 订单信息: {}, 错误信息: {}", JSON.toJSON(zyOrderDO), e.getMessage());
            }
        }
    }

    @Override
    public JSONObject listOrder(Integer pageNum, Integer pageSize, String productName, String userAccount, String userName) {
        JSONObject retObj = new JSONObject();
        Page page = PageHelper.startPage(pageNum, pageSize);
        PageHelper.orderBy(" create_time desc ");
        List<ZyOrderDO> retList = zyOrderMapper.listOrder(productName, userAccount, userName);
        retObj.put(KEY_TOTAL, page.getTotal());
        retObj.put(KEY_INFO_LIST, retList);
        return retObj;
    }

    @Override
    public JSONObject listSendOrder(Integer pageNum, Integer pageSize, String productName, String userAccount, String userName) {
        JSONObject retObj = new JSONObject();
        Page page = PageHelper.startPage(pageNum, pageSize);
        PageHelper.orderBy(" have_send_book ASC, create_time desc ");
        List<ZyOrderDO> retList = zyOrderMapper.listSendOrder(productName, userAccount, userName);
        retObj.put(KEY_TOTAL, page.getTotal());
        retObj.put(KEY_INFO_LIST, retList);
        return retObj;
    }

    @Override
    public Boolean remarkOrder(Integer id, String remark) {
        return zyOrderMapper.remarkOrder(id, remark);
    }

    @Override
    public Boolean sendBook(Integer id) {
        return zyOrderMapper.sendBook(id);
    }

    /**
     * 获取优惠码面值
     *
     * @param couponId    Integer
     * @param userAccount String
     * @return int
     * @throws Exception Exception
     */
    private int getCouponPrice(Integer couponId, String userAccount) throws Exception {
        int couponPrice = 0;
        if (couponId != null) {
            ZyCouponDO zyCouponDO = zyCouponMapper.getById(couponId);
            if (zyCouponDO == null || zyCouponDO.getCouponStatus() != CouponStatusEnum.WAIT_USE) {
                throw new Exception("优惠券不存在!");
            }
            if (zyCouponDO.getCouponStatus() != CouponStatusEnum.WAIT_USE) {
                throw new Exception("优惠券已使用!");
            }
            if (!StringUtils.equals(userAccount, zyCouponDO.getUserAccount())) {
                throw new Exception("优惠券不属于您!");
            }
            zyCouponMapper.usedCoupon(couponId);
            couponPrice = zyCouponDO.getPrice();
        }
        return couponPrice;
    }

}

